Vuex 简单使用

Vuex是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适用于大中型单页应用(SPA)

什么时候,我们需要用到 Vuex 呢?

其实上面的概念已经告诉我们了,即集中式的管理所有组件的状态,简单的说,就是当我们的应用遇到多个组件共享状态的时候,导致单向数据流的简洁性很容易被破坏。例如:商城项目的购物车数量状态,你可以在很多地方修改购物车里的商品状态和商品数量。这时候我们的 Vuex 就登场了,可以很轻松的管理购物车的状态。

Vuex思想流程图:

其实可以说,在 vue 中,所有组件 data 里面的变量都可以称为 State,也可以说是 vue 项目的首要核心概念,我们在 vue 里面使用状态去管理和操控我们的 dom,而不是像过去那样直接操控我们的 dom。即:通过 state 驱动应用的数据源,以声明方式将 state 映射到视图(view),通过 actions,响应在 view 上的用户输入导致的 state 的状态变化:

注意:上面说过,上图的单项数据流在多个组件共享状态很容易遭到破坏,所以我们才有了Vuex.

Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态(State是唯一数据源),每个应用将仅仅包含一个 store 实例。

至于 Vuex 的其他具体核心概念和细节,这里就不再多说了,官方文档写的特详细:Vuex官网

简单使用

利用 Vuex 记录登陆状态与购物车商品数量

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import Vuex from 'vuex'

Vue.use(Vuex);

const store = new Vuex.Store({
state: {
nickName:'',
cartCount:0
},
mutations: {
//用户登陆状态信息
updateUserInfo(state, nickName) {
state.nickName = nickName;
},
//购物车数量
updateCartCount(state,cartCount){
state.cartCount += cartCount;
},
//初始化购物车数量
initCartCount(state,cartCount){
state.cartCount = cartCount;
}
}
});

new Vue({
el: '#app',
store,
router,
template: '<App/>',
//render: h => h(App),
components: { App }
});//.$mount('#app')

在 Header.vue 组件中通过 this.$store.commit("mutationsName",args); 提交修改 nickName 状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import axios from 'axios'
import { mapState } from 'vuex' //辅助函数 mapState 生成计算属性

export default{
data(){
return{
userName:'',
userPwd:'',
errorTip: false,
loginModelFlag: false,
//nickName:''
}
},
computed:{
...mapState([ //利用拓展运算符...将此对象混入到外部对象中,等价于下面注释的写法
'nickName',
'cartCount'
])

/*
mapState([
// 映射 this.count 为 store.state.count
'nickName',
'cartCount'
])
*/

// nickName(){
// return this.$store.state.nickName;
// },
// cartCount(){
// return this.$store.state.cartCount;
// }
},
mounted(){
this.checkLogin();
},
methods:{
checkLogin(){
axios.get('users/checkLogin').then((response) => {
var res = response.data;
if(res.status == "0"){
//this.nickName = res.result;
this.$store.commit("updateUserInfo",res.result);
this.getCartCount();
}else{
if(this.$route.path != '/goods'){
this.$router.push("/goods")
}
}
});
},
login(){
if(!this.userName || !this.userPwd){
this.errorTip = true;
return;
}
axios.post('/users/login',{
userName: this.userName,
userPwd: this.userPwd
}).then((response) => {
let res = response.data;
if(res.status === '0'){
this.errorTip = false;
this.loginModelFlag = false;
//this.nickName = res.result.userName;
this.$store.commit("updateUserInfo",res.result.userName);
this.getCartCount();
//to-do
}else{
this.errorTip = true;
}
});
},
logout(){
axios.post('users/logout').then((response) => {
let res = response.data;
if(res.status === '0'){
//this.nickName = '';
this.$store.commit("updateUserInfo",'');
}
});
},
getCartCount(){
axios.get("/users/getCartCount").then((response) => {
let res = response.data;
this.$store.commit("initCartCount",res.result);
});
}
}
}

在 Cart.vue 中修改 cartCount 状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import axios from 'axios'
import {currency} from "@/util/currency";

export default{
data(){
return{
cartList:[],
productId:'',
modalConfirm: false,
delProductNum: 1,
}
},
components:{
NavHeader,
NavBread,
NavFooter,
Modal
},
mounted(){
this.init();
},
// filters:{//局部过滤器
// currency:currency
// },
computed:{
checkAllFlag(){
return this.checkedCount == this.cartList.length;
},
checkedCount(){
var i = 0;
this.cartList.forEach((item) => {
if(item.checked == '1'){
i++;
}
});
return i;
},
totalPrice(){
var money = 0;
this.cartList.forEach((item) => {
if(item.checked == '1'){
money += parseFloat(item.salePrice) * parseFloat(item.productNum);
}
});
return money;
}
},
methods:{
init(){
axios.get("/users/cartList").then((response) => {
let res = response.data;
this.cartList = res.result;
});
},
delCartConfirm(productId,productNum){
this.modalConfirm = true;
this.productId = productId;
this.productNum = productNum;
},
delCart(){
axios.post("/users/cartDel",{
productId: this.productId
}).then((response) => {
let res = response.data;
if(res.status === "0"){
this.modalConfirm = false;
this.$store.commit("updateCartCount",-(this.productNum))
this.init();
}
});
},
closeModal(){
this.modalConfirm = true;
},
editCart(flag,item){
if(flag == "add"){
item.productNum++;
}else if(flag == "minu"){
if(item.productNum <= 1){
return;
}else{
item.productNum--;
}
}else{
item.checked = item.checked == "1" ? "0":"1";
//item.checked == "1" ? item.checked="0": item.checked="1";
}

axios.post("/users/cartEdit",{
"productId":item.productId,
"productNum":item.productNum,
"checked":item.checked
}).then((response) => {
let res = response.data;
var num = 0;
if(flag == 'add'){
num = 1;
}else if(flag == 'minu'){
num = -1;
}
this.$store.commit("updateCartCount",num);
});
},
toggleCheckAll(){
let flag = !this.checkAllFlag;
this.cartList.forEach((item) => {
item.checked = flag ? "1" : "0";
});
axios.post("/users/editCheckAll",{
checkAll : flag
}).then((response) => {
let res = response.data;
if(res.status == "0"){
console.log("updata success");
}
})
},
checkOut(){
if(this.checkedCount > 0){
this.$router.push({
path:"/address"
});
}
}

}
}



完~